"""DHCP相关模型."""

from datetime import datetime
from typing import Optional

from sqlalchemy import (
    Boolean,
    DateTime,
    ForeignKey,
    Index,
    Integer,
    String,
    Text,
    UniqueConstraint,
)
from sqlalchemy.orm import Mapped, mapped_column, relationship

from .base import Base


class DHCPScope(Base):
    """DHCP作用域模型."""
    
    __tablename__ = "dhcp_scope"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
    description: Mapped[Optional[str]] = mapped_column(Text)
    
    # 网络配置
    subnet: Mapped[str] = mapped_column(String(43), nullable=False)  # 子网地址
    netmask: Mapped[str] = mapped_column(String(15), nullable=False)
    
    # IP范围
    start_ip: Mapped[str] = mapped_column(String(39), nullable=False)
    end_ip: Mapped[str] = mapped_column(String(39), nullable=False)
    
    # DHCP选项
    gateway: Mapped[Optional[str]] = mapped_column(String(39))
    dns_servers: Mapped[Optional[str]] = mapped_column(String(255))  # 逗号分隔
    domain_name: Mapped[Optional[str]] = mapped_column(String(255))
    lease_time: Mapped[int] = mapped_column(Integer, default=3600)  # 秒
    
    # 状态
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    
    # 外键关联
    network_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("ip_network.id"), nullable=False
    )
    
    # 关联
    reservations: Mapped[list["DHCPReservation"]] = relationship(
        "DHCPReservation", back_populates="scope", cascade="all, delete-orphan"
    )
    leases: Mapped[list["DHCPLease"]] = relationship(
        "DHCPLease", back_populates="scope", cascade="all, delete-orphan"
    )
    
    # 约束
    __table_args__ = (
        Index("idx_scope_network", "network_id"),
        Index("idx_scope_active", "is_active"),
    )


class DHCPReservation(Base):
    """DHCP保留地址模型."""
    
    __tablename__ = "dhcp_reservation"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    
    # 基本信息
    mac_address: Mapped[str] = mapped_column(String(17), nullable=False)  # XX:XX:XX:XX:XX:XX
    ip_address: Mapped[str] = mapped_column(String(39), nullable=False)
    hostname: Mapped[Optional[str]] = mapped_column(String(255))
    description: Mapped[Optional[str]] = mapped_column(Text)
    
    # 外键关联
    scope_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("dhcp_scope.id"), nullable=False
    )
    
    # 状态
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    
    # 关联
    scope: Mapped["DHCPScope"] = relationship("DHCPScope", back_populates="reservations")
    
    # 约束
    __table_args__ = (
        UniqueConstraint("mac_address", "scope_id", name="uq_mac_scope"),
        UniqueConstraint("ip_address", "scope_id", name="uq_ip_scope"),
        Index("idx_reservation_scope", "scope_id"),
        Index("idx_reservation_mac", "mac_address"),
    )


class DHCPLease(Base):
    """DHCP租约模型."""
    
    __tablename__ = "dhcp_lease"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    
    # 客户端信息
    mac_address: Mapped[str] = mapped_column(String(17), nullable=False)
    ip_address: Mapped[str] = mapped_column(String(39), nullable=False)
    hostname: Mapped[Optional[str]] = mapped_column(String(255))
    client_id: Mapped[Optional[str]] = mapped_column(String(255))
    
    # 租约时间
    start_time: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False
    )
    end_time: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False
    )
    renewal_time: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False
    )
    rebinding_time: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), nullable=False
    )
    
    # 外键关联
    scope_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("dhcp_scope.id"), nullable=False
    )
    
    # 状态
    state: Mapped[str] = mapped_column(
        String(20), 
        default="active", 
        nullable=False
    )  # active, expired, released
    
    # 关联
    scope: Mapped["DHCPScope"] = relationship("DHCPScope", back_populates="leases")
    ip_address_obj: Mapped[Optional["IPAddress"]] = relationship(
        "IPAddress", back_populates="dhcp_lease"
    )
    
    # 约束
    __table_args__ = (
        UniqueConstraint("mac_address", "ip_address", name="uq_lease_mac_ip"),
        Index("idx_lease_scope", "scope_id"),
        Index("idx_lease_mac", "mac_address"),
        Index("idx_lease_ip", "ip_address"),
        Index("idx_lease_end_time", "end_time"),
        Index("idx_lease_state", "state"),
    )
    
    @property
    def is_active(self) -> bool:
        """检查租约是否活跃."""
        return self.state == "active" and datetime.utcnow() < self.end_time
    
    @property
    def is_expired(self) -> bool:
        """检查租约是否过期."""
        return datetime.utcnow() >= self.end_time